﻿namespace Blaze.Framework.Loaders
{
    using System;
    using System.Collections;
    using Logging;
    using UnityEngine;

    /// <summary>
    /// 用于为内存中的数据加载资源包。
    /// </summary>
    public class MemoryAssetBundleLoader : AssetLoaderBase
    {
        /// <summary>
        /// 获取加载完成的资源包。
        /// </summary>
        public AssetBundle AssetBundle => (AssetBundle) Result;

        public override float Progress
        {
            get
            {
                if (mCreateRequest == null)
                    return 0;
                return mCreateRequest.progress;
            }
        }

        /// <summary>
        /// 设置资源包所对应的内存数据。
        /// </summary>
        public MemoryAssetBundleLoader SetBytes(byte[] bytes)
        {
            mBytes = bytes;
            return this;
        }

        /// <summary>
        /// 当加载器需要被释放时调用此方法。
        /// </summary>
        protected override void OnDispose()
        {
            if (AssetBundle != null)
                AssetBundle.Unload(false);
            mBytes = null;
            base.OnDispose();
        }

        /// <summary>
        /// 当加载器启动时调用此方法。
        /// </summary>
        protected override void OnStart()
        {
            switch (Mode)
            {
                case LoadAssetMode.Async:
                    mCreateRequest = AssetBundle.LoadFromMemoryAsync(mBytes);
                    if (mCreateRequest == null)
                    {
                        mLog.Error("[MemoryAssetBundleLoader]create from memory failed " + Uri);
                        Finish("create from memory failed", null);
                        return;
                    }
                    CoroutineManager.StartNew(wait(mCreateRequest));
                    break;
                case LoadAssetMode.Sync:
                    Finish(null, AssetBundle.LoadFromMemory(mBytes));
                    mBytes = null;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private IEnumerator wait(AssetBundleCreateRequest req)
        {
            while (!req.isDone)
                yield return null;
            Finish(null, req.assetBundle);
            mBytes = null;
        }

        private static readonly Log mLog = LogManager.GetLogger(typeof(MemoryAssetBundleLoader));
        private byte[] mBytes;
        private AssetBundleCreateRequest mCreateRequest;
    }
}